<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Pixiedust Mapbox map</title>
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.32.1/mapbox-gl.js"></script>
    <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.32.1/mapbox-gl.css" rel="stylesheet" />
    <style>
    .mapboxgl-popup-content h3 { 
        margin: 2px 0 2px 0;
        font-style: italic;
    }
    .mapboxgl-popup {
        max-width: 200px;
    }
    #map canvas {
        cursor: crosshair;
    }
    .legend {
        background-color: rgba(255,255,255, 0.75);
        border-radius: 3px;
        position: absolute;
        left: 14px;
        top: 14px;
        box-shadow: 0 1px 2px rgba(0,0,0,0.10);
        font-size: 12px;
        line-height: 18px;
        padding: 10px;
        z-index: 1;
    }
    .legend h4 {
        margin: 0 0 10px;
    }
    .legend div span {
        border-radius: 50%;
        display: inline-block;
        height: 10px;
        margin-right: 5px;
        width: 10px;
    }
    body { 
        background-color:#333; 
        margin:0px !important; 
        overflow: hidden;
        font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
    }
    </style>
</head>
<body>
<div id="map-{{prefix}}-{{randomid}}" style="width:calc({{prefwidth}}px - 4px);height:calc({{prefheight}}px - 4px)" />

{% if this.options.get("kind") and this.options.get("kind").find("simple") < 0 and this.options.get("legend") == "true" %}
<div id="maplegend" class="legend">
    <h4>{{this.options.get("mapValueField")}}</h4>
    {% for bin in bins %}
    <div><span style="background-color: {{bin[1]}}"></span>{{bin[0]}}</div>
    {% endfor %}
</div>
{%endif%}
<script>
    {%include "geojson-extent.js"%}    
    var comment = "";
    mapboxgl.accessToken="{{this.options.get('mapboxtoken')}}";
    var mapdata = null;
    var map = new mapboxgl.Map({
        container: "map-{{prefix}}-{{randomid}}",
        style: "mapbox://styles/mapbox/{{this.options.get('basemap', 'light-v9')}}"
    });

    setTimeout(function(){
        if (window.addPDMessageListener){
            window.addPDMessageListener(function(event){
                streamingLayer = map.getSource("streamingLayer");
                if (streamingLayer){
                    streamingLayer.setData(event.data.data);
                }else{
                    map.addLayer({
                        "id": "streamingLayer",
                        "maptype": "mapbox",
                        "type": event.data.type,
                        "source": { type: "geojson", data: event.data.data },
                        "layout": event.data.layout || {},
                        "paint": event.data.paint || {}
                    });
                    if (event.data.fitbounds && event.data.data.features){
                        function updateBounds(res, ar){
                            if (ar[0].length >=2 && ar[1].length >= 2 ){
                                if (!res){
                                    return ar;
                                }
                                return [ 
                                    [Math.min( ar[0][0]-0.1, res[0][0]), Math.min( ar[0][1]-0.1, res[0][1])],
                                    [Math.max( ar[1][0]+0.1, res[1][0]), Math.max( ar[1][1]+0.1, res[1][1])]
                                ]
                            }
                            return null;
                        }
                        var bbox = event.data.data.features.reduce(function(res, value){
                            var coord = value.geometry.coordinates;
                            if (coord.length >= 2 ){
                                res = updateBounds( res, [coord[0], coord[1]]);
                            }
                            return res;
                        }, null);
                        if (bbox){
                            map.fitBounds(bbox);
                        }
                    }
                }
            });
        };
    },100);

    var popup = new mapboxgl.Popup({closeButton: false,closeOnClick: true});

    function divineGeometryType(mapdata) {
        comment = "check type of first geometry. Later expand to check all geometries and make a good decision";
        return mapdata.features[0].geometry.type;
    }
    
    map.on("mousemove", function (e) {
        var fs = map.queryRenderedFeatures(e.point,{layers:["pxlayer"{%for l in userlayers%},"{{l['id']}}"{%endfor%}]});
        if (!fs || !fs.length) {popup.remove();return;};
        popuphtml = "";
        var hr = false;
        fs.forEach(function(f){
            if (hr){ 
                popuphtml += "<hr>\n";
            }
            hr=true;
            popuphtml += "<h3>"+f.layer.id.toUpperCase()+"</h3>\n";
            var keylength = Object.keys(f.properties).length;
            for (var key in f.properties) {
                popuphtml += "<b>"+key+": </b> "+f.properties[key]+"<br/>\n";
            }
        });
        popup.setLngLat(e.lngLat).setHTML(popuphtml).addTo(map);
    });
    
    map.on("click", function (e) {
        var fs = map.queryRenderedFeatures(e.point, { layers: ["pxlayer"] });
        if (fs && fs.length) {
            var f = fs[0];
            console.log("clicked", f);
            var keylength = Object.keys(f.properties).length;
            var payload = {type:"select", targetDivId: "{{this.options.get("targetDivId","") }}" };

            for (var key in f.properties) {
                payload[key] = f.properties[key];
            }

            if (window.triggerPDEvent) {
                window.triggerPDEvent(payload);
            }
        }
    });
        
    map.on("load", function() {
        {% if this.options.get("mapData") %}
        mapdata={{this.options.get("mapData")}};
        geomtype = divineGeometryType(mapdata);
        {%if this.options.get("kind") != "densitymap" %}
            var ds = {
                "type":"geojson",
                "data":mapdata
            };
            var clusterme = false;
            if (geomtype.substr(-5,5) == "Point") {
                {% if this.options.get("kind") and this.options.get("kind").find("cluster") >= 0 %}
                    clusterme = true;
                    ds["cluster"] = true;
                    ds["clusterMaxZoom"] = 14;
                    ds["clusterRadius"] = 20;
                    console.log("IM CLUSTERED");
                {% endif %}
            }
            map.addSource("pxdatasource", ds);

            var maplayertype = "circle";
            if (geomtype.substr(-7,7) == "Polygon") 
                maplayertype = "fill";
            else if (geomtype.substr(-10,10) == "LineString")
                maplayertype = "line";
            map.addLayer({
                "id":"pxlayer",
                "type":maplayertype, 
                "source": "pxdatasource", 
                "paint": {{this.options.get("mapStyle")}}
            });
            
            if (clusterme && geomtype.substr(-5,5) == "Point") {
                map.addLayer({
                    "id": "cluster-count-labels", 
                    "type": "symbol", 
                    "source": "pxdatasource", 
                    "paint": {
                        "text-color": "#FFF"
                    },
                    "layout": {
                        "text-field": "{point_count}", 
                        "text-font": [
                            "DIN Offc Pro Medium", 
                            "Arial Unicode MS Bold"
                        ],
                        "text-size": 12
                    }
                });
            }
        {% else %}
        comment = "this is a densitymap...";
        map.addSource("pxdatasource", {
            "type":"geojson",
            "data":mapdata,
            "cluster": true, 
            "clusterMaxZoom": 11, 
            "clusterRadius": 20
        });
        var layers = [];
        {% for bin in bins %}
            layers.push([{{bin[0]}}, "{{bin[1]}}"]);
        {% endfor %}

        layers.forEach(function(layer,i) {
            map.addLayer({
                "id": "cluster-" + i, 
                "type": "circle", 
                "source": "pxdatasource", 
                "paint": {
                    "circle-color": layer[1],
                    "circle-radius": 70, 
                    "circle-blur": 1
                }, 
                "filter": i === layers.length-1 ? [">=", "{{this.options.get("mapValueField")}}", layer[0]] : 
                    ["all", [">=", "{{this.options.get("mapValueField")}}", layer[0]], ["<", "{{this.options.get("mapValueField")}}", layers[i+1][0]]]

            }, "waterway-label");
        });
        
        map.addLayer({
            "id": "pxlayer", 
            "type": "circle", 
            "source": "pxdatasource", 
            "paint": {
                "circle-color": "rgba(0,255,0,0.5)", 
                "circle-radius": 20, 
                "circle-blur": 1
            }, 
            "filter": ["!=", "cluster", true]
        }, "waterway-label");

        {% endif %}
        {% endif %}

        comment = "Add user layers";
        var layers = [];
        {% for layer in userlayers %}
            var layertype = "circle";
            {% if layer["type"] %}
            layertype = {{layer["type"]|jsonify}};
            {%endif%}
            
            var layerpaint = {};
            {% if layer["paint"] %}
            layerpaint = {{layer["paint"]|jsonify}};
            {%endif%}

            var layerlayout = {};
            {% if layer["layout"] %}
            layerlayout = {{layer["layout"]|jsonify}};
            {%endif%}

            var newlayer = {
                "id": {{layer["id"]|jsonify}},
                "type": layertype, 
                "source": {{layer["source"]|jsonify}},
                "paint": layerpaint, 
                "layout": layerlayout
            };
            layers.push([newlayer, {{layer["order"]|jsonify}}]);
        {% endfor %}
        layers.sort(function(a,b) {
            return a[1] - b[1];
        });
        for (layersi=layers.length-1; layersi>=0; layersi--) {
            map.addLayer(layers[layersi][0]);
            comment = "User layer legend";
            {%if this.options.get("legend") == "true" %}
                var t = document.createElement("h4");
                t.appendChild(document.createTextNode(layers[layersi][0].id));
                document.getElementById("maplegend").appendChild(t);
            {% endif %}
        }
        {%if this.options.get("mapBounds") %}
        map.fitBounds({{this.options.get("mapBounds")}});
        {%else%}
        var bounds = geojsonExtent(mapdata);
        if (bounds){
            map.fitBounds(geojsonExtent(mapdata));
        }      
        {%endif%}
        
    });
</script>
</body>
</html>
